package cn.bdqn.config.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.bdqn.pojo.SysRight;
import cn.bdqn.service.SysRightService;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Resource
    SysRightService sysRightService;
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    /**
     * 开启 Shiro 注解(如@RequiresRoles,@RequiresPermissions),
     * 需借助 SpringAOP 扫描使用 Shiro 注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个 bean(DefaultAdvisorAutoProxyCreator 和
     AuthorizationAttributeSourceAdvisor)
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=
                new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /**
     * 开启aop注解支持
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor
    authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor=
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    public MyRealm myRealm(){
     MyRealm myRealm =new MyRealm();
     //开启缓存
        myRealm.setCachingEnabled(true);
        //开启授权缓存
        myRealm.setAuthorizationCachingEnabled(true);
        //设置授权缓存名称
        myRealm.setAuthorizationCacheName("authrizationCache");

        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myRealm;
    }
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myRealm());
        defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager());
        defaultWebSecurityManager.setSessionManager(defaultWebSessionManager());
        defaultWebSecurityManager.setCacheManager(redisCacheManager());
        return defaultWebSecurityManager;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(){
        ShiroFilterFactoryBean factoryBean=new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(defaultWebSecurityManager());
        //
        factoryBean.setLoginUrl("/login");
        factoryBean.setSuccessUrl("/main");
        factoryBean.setUnauthorizedUrl("/403");
        Map<String,String> filterMap=new LinkedHashMap<>();
        filterMap.put("/css/**","anon");
        filterMap.put("/fonts/**","anon");
        filterMap.put("/images/**","anon");
        filterMap.put("/js/**","anon");
        filterMap.put("/localcss/**","anon");
        filterMap.put("/localjs/**","anon");
        filterMap.put("/dologin","anon");
        filterMap.put("/logout","logout");
             //静态演示
//        filterMap.put("/user/list","perms[用户列表]");
//        filterMap.put("/user/add","perms[用户添加]");
////        filterMap.put("/user/edit","perms[用户编辑]");
//        filterMap.put("/user/delete","perms[用户删除]");
//        filterMap.put("/**","authc");
        List<SysRight> lists = sysRightService.selectAll();
        if (lists!=null){
            for (SysRight list : lists) {
                if (list.getRightUrl()!=null && !list.getRightUrl().trim().equals("")){
                    filterMap.put(list.getRightUrl(),"perms["+list.getRightCode()+"]");
                }
            }
        }
        filterMap.put("/**","authc");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;

    }
    @Bean
    public SimpleCookie simpleCookie(){
        SimpleCookie cookie=new SimpleCookie("rememberMe");
        cookie.setMaxAge(500000);
        return cookie;
    }
    @Bean
    public CookieRememberMeManager cookieRememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager=new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(simpleCookie());
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }
    
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
    @Bean
    public RedisManager redisManager(){
        RedisManager redisManager=new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }
    @Bean
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO=new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(){
        DefaultWebSessionManager defaultSessionManager=new DefaultWebSessionManager();
        defaultSessionManager.setSessionDAO(redisSessionDAO());
        return defaultSessionManager;
    }
    @Bean
    public RedisCacheManager redisCacheManager(){
        RedisCacheManager redisCacheManager=new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        //设置缓存名称key
        redisCacheManager.setPrincipalIdFieldName("usrName");
        //缓存有效期
        redisCacheManager.setExpire(30*60);
        return redisCacheManager;
    }
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher=new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }
}
